home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Tools & Apps / Networking & Communications / Network Watch (DMZ) 1.0 / dmz.a next >
Encoding:
Text File  |  1992-08-17  |  20.7 KB  |  593 lines  |  [TEXT/MPS ]

  1. ;_________________________________________________________________________
  2. ;
  3. ; dmz.a
  4. ;_________________________________________________________________________
  5. ;
  6. ; DTS Code Sample
  7. ;    
  8. ; ©1990 Apple Computer, Inc.
  9. ;
  10. ; 3/7/90 - 10/26/90 pvh
  11. ;
  12. ;_________________________________________________________________________
  13.  
  14.     PRINT    PUSH,OFF        ; don't print any of this stuff
  15.  
  16.     INCLUDE 'QuickEqu.a'
  17.     INCLUDE 'ToolEqu.a'
  18.     INCLUDE 'SysEqu.a'
  19.     INCLUDE 'Traps.a'
  20.     INCLUDE 'ATalkEqu.a'
  21.     INCLUDE    'SysErr.a'        
  22.     
  23.     PRINT    POP                ; restore the PRINT options
  24.  
  25.         
  26. ;---------------------------------------
  27. mySaveA5    PROC     EXPORT
  28.              
  29.             movea.l    (a7)+, a1        ; save the return address
  30.             MOVE.L     a5, -(a7)       ; move current a5 onto stack
  31.             movea.l $2C(a0), a5        ; get 'our' a5 from saved paramBlock
  32.             jmp        (a1)            ; return to sender
  33.             
  34.             ENDP
  35.             
  36. ;---------------------------------------
  37. myRestoreA5    PROC     EXPORT
  38.              
  39.             movea.l    (a7)+, a1        ; save the return address
  40.             MOVE.L (a7)+, a5          ; move saved a5 back into a5
  41.             jmp        (a1)            ; return to sender
  42.             
  43.             ENDP
  44.             
  45. ;---------------------------------------
  46. RestoreA5    PROC     EXPORT
  47.              
  48.             MOVE.L (a7)+, a5          ; move saved a5 back into a5
  49.             
  50.             ENDP
  51.  
  52. ; Socket Listener Sample
  53. ;
  54. ; 3/92 Jim Luther,  Apple DTS
  55. ;
  56. ; ©1992 Apple Computer, Inc.
  57. ;_________________________________________________________________________
  58.  
  59.     INCLUDE    'QuickEqu.a'
  60.     INCLUDE    'ToolEqu.a'
  61.     INCLUDE    'SysEqu.a'
  62.     INCLUDE    'Traps.a'
  63.     INCLUDE    'ATalkEqu.a'
  64.     INCLUDE    'SysErr.a'
  65.  
  66. ;
  67. ;
  68. ; Record Types
  69. ;
  70. ;_________________________________________________________________________
  71.  
  72. QHdr                  RECORD    0
  73. qFlags                DS.W      1
  74. qHead                 DS.L      1
  75. qTail                 DS.L      1
  76.                       ENDR
  77.  
  78. PacketBuffer          RECORD    0
  79. qLink                 DS.L      1
  80. qType                 DS.W      1
  81. buffer_Type           DS.W      1            ; DDP Type
  82. buffer_NodeID         DS.W      1            ; Destination node
  83. buffer_Address        DS.L      1            ; Source address in AddrBlock format
  84. buffer_Hops           DS.W      1            ; Hop count
  85. buffer_ActCount       DS.W      1            ; length of DDP datagram
  86. buffer_CheckSum       DS.W      1            ; Chksum error returned here (cksumErr or noErr)
  87. buffer_Ticks          DS.W      1             ; TickCount when handler called
  88. buffer_Data           DS.B      ddpMaxData   ; the DDP datagram
  89.                       ENDR
  90.  
  91. ;_________________________________________________________________________
  92. ;
  93. ; Local Variables
  94. ;
  95. ;_________________________________________________________________________
  96.  
  97. SL_Locals    PROC
  98.         ENTRY free_queue,used_queue,current_qelem
  99.  
  100. free_queue        DC.L    0        ; pointer to freeQ QHdr - initialized by InitSktListener
  101. used_queue        DC.L    0        ; pointer to usedQ QHdr - initialized by InitSktListener
  102. current_qelem     DC.L    0        ; pointer to current PacketBuffer record
  103.                                    ; initialized by InitSktListener, then
  104.                                    ; set by socket listener after every packet.
  105.                                    ; NIL if no buffer is available.
  106.     ENDP
  107.  
  108. ;_________________________________________________________________________
  109. ;
  110. ; SL_DoChksum - accumulate ongoing checksum (from Inside Macintosh)
  111. ;
  112. ;    Input:
  113. ;     D1 (word) = number of bytes to checksum
  114. ;     D3 (word) = current checksum
  115. ;     A1 points to the bytes to checksum
  116. ;
  117. ;    Return:
  118. ;     D0 is modified
  119. ;     D3 (word) = accumulated checksum
  120. ;_________________________________________________________________________
  121.  
  122. SL_DoChksum    PROC
  123.     CLR.W      D0                    ; Clear high byte
  124.     SUBQ.W     #1,D1                 ; Decrement count for DBRA
  125. ChksumLoop:
  126.     MOVE.B     (A1)+,D0              ; read a byte into D0
  127.     ADD.W      D0,D3                 ; accumulate checksum
  128.     ROL.W      #1,D3                 ; rotate left one bit
  129.     DBRA       D1,ChksumLoop         ; loop if more bytes
  130.     RTS
  131.     ENDP
  132.  
  133. ;_________________________________________________________________________
  134. ;
  135. ; SL_TheListener
  136. ;
  137. ;_________________________________________________________________________
  138.  
  139. ;_________________________________________________________________________
  140. ;
  141. ; SL_TheListner - process packets received at the designated socket
  142. ;
  143. ;    Input:
  144. ;     D0 (byte) = packet's destination socket number
  145. ;     D1 (word) = number of bytes left to read in packet
  146. ;     A0 points to the bytes to checksum
  147. ;     A1 points to the bytes to checksum
  148. ;     A2 points to MPP's local variables
  149. ;     A3 points to next free byte in Read Header Area
  150. ;     A4 points to ReadPacket and ReadRest jump table
  151. ;
  152. ;    Return:
  153. ;     D0 is modified
  154. ;     D3 (word) = accumulated checksum
  155. ;_________________________________________________________________________
  156. SL_TheListener  PROC    EXPORT
  157.  
  158.     WITH    PacketBuffer
  159.  
  160. ; get pointer to current PacketBuffer
  161.  
  162. GetBuffer:
  163.     LEA       current_qelem,A3                ; get the pointer to the PacketBuffer to use
  164.     MOVE.L    (A3),A3
  165.     MOVE.L    A3,D0                           ; if no PacketBuffer
  166.     BEQ.S     NoBuffer                        ; then ignore packet
  167.  
  168. ; read rest of packet into PacketBuffer.datagramData
  169.  
  170.     MOVE.L    D1,D3                           ; read rest of packet
  171.     LEA       buffer_data(A3),A3              ; A3 = ^bufferData
  172.     JSR       2(A4)                           ; ReadRest
  173.     BEQ.S     ProcessPacket                   ; If no error, continue
  174.     BRA       RcvRTS                          ; there was an error, so ignore packet
  175.  
  176. ; No buffer; ignore the packet
  177.  
  178. NoBuffer      CLR D3                          ; Set to ignore packet (buffer size = 0)
  179.     JSR       2(A4)                           ; ReadRest
  180.     BRA       GetNextBuffer                   ; We missed this packet, but maybe there
  181.                                               ; will be a buffer for the next packet…
  182.  
  183. ; Process the packet you just read in.
  184. ; ReadRest has been called so registers A0-A3 and D0-D3 are free to use.
  185. ; We'll use registers this way:
  186. PktBuff         EQU    A0        ; the current PacketBuffer
  187. MPPLocals       EQU    A2        ; pointer to MPP's local variables (still set up 
  188.                                  ;  from entry to socket listener)
  189. HopCount        EQU    D0        ; used to get the hop count
  190. DatagramLength  EQU    D1        ; used to determine the datagram length
  191. SourceNetAddr   EQU    D2        ; used to build the source network address
  192.  
  193. ProcessPacket:
  194.     LEA        current_qelem,PktBuff          ; PktBuff = current_qelem
  195.     MOVE.L     (PktBuff),PktBuff
  196.  
  197. ; do everything that's common to both long and short DDP headers
  198.  
  199. ; save tickCount in buffer_Ticks field
  200.  
  201.     MOVE.L       Ticks,buffer_Ticks(PktBuff)
  202.  
  203. ; first, clear buffer_Type and buffer_NodeID to ensure their high bytes are 0
  204.  
  205.     CLR.W      buffer_Type(PktBuff)           ; clear buffer_Type
  206.     CLR.W      buffer_NodeID(PktBuff)         ; clear buffer_NodeID
  207.  
  208. ; clear SourceNetAddr to prepare to build network address
  209.  
  210.     MOVEQ      #0,SourceNetAddr               ; build the network address in SourceNetAddr
  211.  
  212. ; get the hop count
  213.     MOVE.W     toRHA+lapHdSz+ddpLength(MPPLocals),HopCount ; Get hop/length field
  214.     ANDI.W     #DDPHopsMask,HopCount          ; Mask off the hop count bits
  215.     LSR.W      #2,HopCount                    ; shift hop count into low bits of high byte 
  216.     LSR.W      #8,HopCount                    ; shift hop count into low byte
  217.     MOVE.W     HopCount,buffer_Hops(PktBuff)  ; and move it into the PacketBuffer
  218.  
  219. ; get the packet length (including the DDP header)
  220.     MOVE.W     toRHA+lapHdSz+ddpLength(MPPLocals),DatagramLength ; Get length field
  221.     ANDI.W     #ddpLenMask,DatagramLength     ; Mask off the hop count bits
  222.  
  223. ; now, find out if the DDP header is long or short
  224.  
  225.     MOVE.B     toRHA+lapType(MPPLocals),D3    ; Get LAP type
  226.     CMPI.B     #shortDDP,D3                   ; is this a long or short DDP header?
  227.     BEQ.S      IsShortHdr                     ; skip if short DDP header
  228.  
  229. ; it's a long DDP header
  230.  
  231.     MOVE.B     toRHA+lapHdSz+ddpType(MPPLocals),buffer_Type+1(PktBuff) ; get DDP type
  232.  
  233.     MOVE.B     toRHA+lapHdSz+ddpDstNode(MPPLocals),buffer_NodeID+1(PktBuff) 
  234.                                               ; get destination node from LAP header
  235.  
  236.     MOVE.L     toRHA+lapHdSz+ddpSrcNet(MPPLocals),SourceNetAddr 
  237.                                               ; source network in hi word
  238.                                               ; source node in lo byte
  239.     LSL.W      #8,SourceNetAddr               ; shift source node up to high byte of low word
  240.                                               ; get source socket from DDP header
  241.     MOVE.B     toRHA+lapHdSz+ddpSrcSkt(MPPLocals),SourceNetAddr 
  242.  
  243.     SUB.W      #ddpType+1,DatagramLength      ; DatagramLength = number of bytes in datagram
  244.     BRA.S      MoveToBuffer
  245.  
  246. ; checksum time…
  247.     TST.W      toRHA+lapHdSz+ddpChecksum(MPPLocals) ;Does packet have checksum?
  248.     BEQ.S      noChecksum
  249.  
  250. ; Calculate checksum over DDP header
  251.     MOVE.L     DatagramLength,-(SP)           ; save DatagramLength (D1)
  252.  
  253.     CLR        D3                             ; set checksum to zero
  254.     MOVEQ      #ddphSzLong-ddpDstNet,D1       ; D1 = length of header part to checksum
  255.                                               ; pointer to dest network number in DDP header
  256.     LEA        toRHA+lapHdSz+ddpDstNet(MPPLocals),A1 
  257.     JSR        SL_DoChksum                    ; checksum of DDP header part 
  258.                                               ; (D3 holds accumulated checksum)
  259.  
  260. ; Calculate checksum over data portion (if any)
  261.  
  262.     MOVE.L     buffer_Data(PktBuff),A1        ; pointer to datagram
  263.     MOVE.L     (SP)+,DatagramLength           ; restore DatagramLength (D1)
  264.     MOVE.L     DatagramLength,-(SP)           ; save DatagramLength (D1) 
  265.                                               ;  before calling SL_DoChksum
  266.     BEQ.S      TestChecksum                   ; don't checksum datagram if its length = 0
  267.     JSR        SL_DoChksum                    ; checksum of DDP datagram part 
  268.                                               ; (D3 holds accumulated checksum)
  269.  
  270. TestChecksum:
  271.     MOVE.L     (SP)+,DatagramLength           ; restore DatagramLength (D1)
  272.  
  273. ; Now make sure the checksum is OK.
  274.  
  275.     TST.W      D3                             ; is the calculated value zero?
  276.     BNE.S      NotZero                        ; no -- go and use it
  277.     SUBQ.W     #1,D3                          ; it is 0; make it -1
  278.  
  279. NotZero:
  280.     CMP.W      toRHA+lapHdSz+ddpChecksum(MPPLocals),D3
  281.     BNE.S      ChecksumErr                    ; Bad checksum
  282.     MOVE.W     #0,buffer_CheckSum(A0)         ; no errors
  283.     BRA.S      noChecksum
  284. ChecksumErr:
  285.     MOVE.W     #ckSumErr,buffer_CheckSum(PktBuff) ; checksum error
  286.  
  287. noChecksum:
  288.     BRA.S      MoveToBuffer
  289.  
  290.  
  291. ; it's a short DDP header
  292.  
  293. IsShortHdr:
  294.     MOVE.B     toRHA+lapHdSz+sddpType(MPPLocals),buffer_Type+1(PktBuff) ; get DDP type
  295.     MOVE.B     toRHA+lapDstAdr(MPPLocals),buffer_NodeID+1(PktBuff) 
  296.                                                ; get destination node from LAP header
  297.     MOVE.B     toRHA+lapSrcAdr(MPPLocals),SourceNetAddr ; get source node from LAP header
  298.     LSL.W      #8,SourceNetAddr                ; shift src node up to high byte of low word
  299.     MOVE.B     toRHA+lapHdSz+sddpSrcSkt(MPPLocals),SourceNetAddr 
  300.                                                ; get source socket from short DDP header
  301.     SUB.W      #sddpType+1,DatagramLength      ; DatagramLength = number of bytes in datagram
  302.  
  303. MoveToBuffer:
  304.     MOVE.L     SourceNetAddr,buffer_Address(PktBuff) 
  305.                                                ;move source network address into PacketBuffer
  306.     MOVE.W     DatagramLength,buffer_ActCount(PktBuff) 
  307.                                                ; move datagram length into PacketBuffer
  308.  
  309.  
  310. ; Now that we're done with the PacketBuffer, enqueue it into the usedQ and get
  311. ; another buffer from the freeQ for the next packet.
  312.  
  313.     LEA        used_queue,A1                   ; A1 = ^used_queue
  314.     MOVE.L     (A1),A1                         ; A1 = used_queue (pointer to usedQ)
  315.     _Enqueue                                    ; put the PacketBuffer in the usedQ
  316.  
  317. GetNextBuffer:
  318.     LEA        free_queue,A1                   ; A1 = ^free_queue
  319.     MOVE.L     (A1),A1                         ; A1 = free_queue (pointer to freeQ)
  320.     LEA        current_qelem, A0               ; copy freeQ.qHead into current_qelem
  321.     MOVE.L     qHead(A1),(A0)
  322.     MOVEA.L    qHead(A1),A0                    ; A0 = freeQ.qHead
  323.     _Dequeue
  324.  
  325. RcvRTS:
  326.     RTS                                        ; return to caller
  327.     ENDP
  328.  
  329. ;_________________________________________________________________________
  330. ; Function SL_InitSktListener(freeQ, usedQ: QHdrPtr): OSErr
  331. ;
  332. ;
  333.  
  334. SL_InitSktListener PROC EXPORT
  335.  
  336. StackFrame     RECORD    {A6Link},DECR     ; build a stack frame record
  337. Result1        DS.W      1                 ; function's result returned to caller
  338. ParamBegin     EQU       *                 ; start parameters after this point
  339. freeQ          DS.L      1                 ; freeQ parameter
  340. usedQ          DS.L      1                 ; usedQ parameter
  341. ParamSize      EQU       ParamBegin-*      ; size of all the passed parameters
  342. RetAddr        DS.L      1                 ; placeholder for return address
  343. A6Link         DS.L      1                 ; placeholder for A6 link
  344. LocalSize      EQU       *                 ; size of all the local variables
  345.                ENDR
  346.  
  347.     WITH       StackFrame,QHdr             ; use these record types
  348.  
  349.     LINK       A6,#LocalSize               ; allocate our local stack frame
  350.  
  351. ; copy the queue header pointers into our local storage for use in the listener
  352.  
  353.     LEA        used_queue,A0               ; copy usedQ into used_queue
  354.     MOVE.L     usedQ(A6),(A0)
  355.  
  356.     LEA        free_queue,A0               ; copy freeQ into free_queue
  357.     MOVE.L     freeQ(A6),(A0)
  358.  
  359. ; dequeue the first buffer record from freeQ and set current_qelem to it
  360.  
  361.     MOVEA.L    freeQ(A6),A1                ; A1 = ^freeQ
  362.     LEA        current_qelem, A0           ; copy freeQ.qHead into current_qelem
  363.     MOVE.L     qHead(A1),(A0)
  364.     MOVEA.L    qHead(A1),A0                ; A0 = freeQ.qHead
  365.     _Dequeue
  366.     MOVE.W     D0,Result1(A6)              ; Return status
  367.  
  368. @1  UNLK       A6                          ; destroy the link
  369.     MOVEA.L    (SP)+,A0                    ; pull off the return address
  370.     ADDA.L     #ParamSize,SP               ; strip all of the caller's parameters
  371.     JMP        (A0)                        ; return to the caller
  372.     ENDP
  373.  
  374. ;--------------------------------------
  375. ; myVBLSpinInstall
  376. ;
  377. ; 10/90 pvh
  378. ;
  379. ; I hated the ToolLib spinning cursor routines enough to make up my own.  Those routines
  380. ; are fine if you base your spinning cursor off a tight loop where you can continuously call the 
  381. ; routines to actually spin the cursor.  In my case that library was not ideal, so instead
  382. ; I just threw ('slapped' might be the better term) together a VBL task that spins the cursor
  383. ; instead (ala MacApp).
  384. ;
  385. ; This routine & the clean up routine that follows are pretty mcuh self explanatory.  4 cursors
  386. ; are preloaded & locked so they'll be sure to be available when the VBL task is called.  The 
  387. ; task is set up and moved into the application's heap.  The task itself checks a locally saved
  388. ; variable for the cursor ID, loads in that cursor and sets that cursor as the current one if
  389. ; the cursor state is not currently busy (by checking CrsrBusy).
  390. ; When the task finishes, global references to the VBL task are used in the clean up routine
  391. ; (stopAndRemoveSpinningCursor) to remove the task & associated buffers.  The cursors are also
  392. ; released from memory here.
  393. ;
  394. ; 10/16/90 pvh
  395. ;
  396. ; gMac was imported originally to help support color cursors within this task, but that endeavor
  397. ; was turning out to be too much of a hack (even for me), so it's staying around as a remanant of
  398. ; that failed attempt just to mark another one of my failures.  :-)
  399.  
  400. spinGlobals    RECORD    0        ; this is our global data storage
  401. gtheTaskPtr        DS.L    1        ; pointer to hold task itself
  402. gtheVBLPtr        DS.L    1        ; pointer for VBL task record
  403.           ENDR
  404.  
  405.         EXPORT    (sg):DATA
  406.  
  407. sg            DS    spinGlobals        ; globals for spin cursor
  408.  
  409.  
  410. myVBLSpinInstall    PROC     EXPORT
  411.         IMPORT    gMac : DATA
  412.      
  413. StackFrame    RECORD    {A6Link},DECR        ; build a stack frame record
  414. ParamBegin    EQU    *                        ; start listing parameters here
  415. ParamSize    EQU    ParamBegin-*            ; size of all the passed parameters
  416. RetAddr     DS.L    1                    ; place holder for return address
  417. A6Link        DS.L    1                    ; place holder for A6 link
  418. taskSize     DS.L    1                     ; size of our VBL task
  419. curses        DS.L    4                    ; handle for our cursor
  420. cursType    DS.L    1
  421. LocalSize    EQU     *                    ; size of all the local variables
  422.         ENDR
  423.     
  424.                 WITH    StackFrame, SysEnvRec        ; cover our local stack frame
  425.                 LINK    A6,#LocalSize                ; allocate our local stack frame
  426.                     
  427.                 ; pre-load in the resources to make sure they are around 
  428.                 CLR.L    -(sp)                        ; make space on the stack for result
  429.                 MOVE.L    #'CURS', cursType(a6)        ; another remanant from color stuff (don't ask)
  430.                 MOVE.L    cursType(a6), -(sp)
  431.                 MOVE    #1001, -(sp)
  432.                 _GetResource
  433.                 MOVE.L    (sp)+, curses(a6)
  434.                 MOVE.L    curses(a6), a0
  435.                 _HLock
  436.     
  437.                 CLR.L    -(sp)                        ; make space on the stack for result
  438.                 MOVE.L    cursType(a6), -(sp)
  439.                 MOVE    #1002, -(sp)
  440.                 _GetResource
  441.                 MOVE.L    (sp)+, curses+4(a6)
  442.                 MOVE.L    curses+4(a6), a0
  443.                 _HLock
  444.     
  445.                 CLR.L    -(sp)                        ; make space on the stack for result
  446.                 MOVE.L    cursType(a6), -(sp)
  447.                 MOVE    #1003, -(sp)
  448.                 _GetResource
  449.                 MOVE.L    (sp)+, curses+8(a6)
  450.                 MOVE.L    curses+8(a6), a0
  451.                 _HLock
  452.     
  453.                 CLR.L    -(sp)                        ; make space on the stack for result
  454.                 MOVE.L    cursType(a6), -(sp)
  455.                 MOVE    #1004, -(sp)
  456.                 _GetResource
  457.                 MOVE.L    (sp)+, curses+12(a6)
  458.                 MOVE.L    curses+12(a6), a0
  459.                 _HLock
  460.     
  461.                 BRA.S     theTaskEnd
  462.                 
  463.                 ; actual VBL Task
  464. theTaskBegin
  465.                 MOVEM.L    a0-a6/d0-d7, -(sp)        ; save 
  466.                 BRA.S    afterStorage
  467. A5Storage
  468.                 DC.L    0
  469. afterStorage
  470.                 ; reset the vbl count
  471.                 MOVE.W     #5, vblCount(a0)    
  472.                 
  473.                 ; restore A5 for globals we may have
  474.                 LEA        A5Storage, a0
  475.                 MOVE.L    (a0), a5
  476.                 BRA.S    xxx
  477. cursorStorage                
  478.                 DC.W    $03E9                        ; storage for cursor type, start with first cursor ID
  479. xxx                
  480.                 LEA        cursorStorage, a0
  481.                 ADD.W    #1, (a0)
  482.                 MOVE.W    (a0), d0
  483.                 CMP.W    #1005, d0
  484.                 BLT.S    doCursor
  485.                 
  486.                 MOVE.W    #1001, (a0)                    ; start over with cursor type #1001
  487.                 MOVE.W    #1001, d0                    ; it needs to be in d0
  488. doCursor        
  489.                 CLR.L    -(a7)                        ; make some space for return
  490.                 MOVE.W    d0, -(a7)                    ; move in cursor type
  491.                 _GetCursor
  492.                 MOVE.L    (a7)+, a0                    ; move handle into a0
  493.                 BEQ.S    vblExit                        ; test for nil handle
  494.                 tst.b    CrsrBusy                    ; cursor drawing as we speak?  then split.
  495.                 BNE.S    vblExit
  496.                 MOVE.L    (a0), -(a7)                    ; deref and push on stack
  497.                 _SetCursor            
  498. vblExit
  499.                 MOVEM.L     (sp)+, a0-a6/d0-d7            ; restore 
  500.                 rts
  501. theTaskEnd
  502.                 
  503.                 ; VBL initialization code
  504.                 LEA        theTaskEnd, a0                ; address of tail of task
  505.                 LEA        theTaskBegin, a1            ; head of task
  506.                 MOVE.L    a0, d0                        ; get size of task
  507.                 SUB.L    a1, d0
  508.                 MOVE.L    d0, taskSize(a6)
  509.                 
  510.                 LEA        A5Storage, a0                ; put current A5 into our storage area in code
  511.                 MOVE.L    CurrentA5, (a0)
  512.             
  513.                 ; set up VBL record
  514.                 MOVE.L    #vblPhase+2, d0                ; size of VBLTask
  515.                 _NewPtr    
  516.                 MOVE.L    a0, sg.gtheVBLPtr(a5)
  517.                 
  518.                 ; setup block of memory to hold task itself (in our heap, not the System heap)
  519.                 MOVE.L    taskSize(a6), d0
  520.                 _NewPtr
  521.                 MOVE.L    a0, sg.gtheTaskPtr(a5)
  522.             
  523.                 ; move the task code into block in heap
  524.                 LEA        theTaskBegin, a0            ; head of task
  525.                 MOVE.L    sg.gTheTaskPtr(a5), a1
  526.                 MOVE.L    taskSize(a6), d0
  527.                 _BlockMove
  528.             
  529.                 MOVE.L     sg.gtheTaskPtr(a5), a1
  530.                 MOVE.L    sg.gtheVBLPtr(a5), a0
  531.                 MOVE.L    a1, vblAddr(a0)                ; a1 contains address of moved TheTask
  532.                 MOVE.W     #vType, qType(a0)
  533.                 MOVE.W     #10, vblCount(a0)
  534.                 MOVE.W     #4, vblPhase(a0)            ; whatever
  535.                 _VInstall
  536.     
  537. Exit            UNLK    A6                ; destroy the link
  538.                 MOVEA.L    (SP)+,A0        ; pull off the return address
  539.                 ADDA.L    #ParamSize,SP    ; strip all of the caller's parameters
  540.                 JMP    (A0)                ; return to the caller
  541.             
  542.         ENDP
  543.  
  544. ;--------------------------------------
  545. ; this routine disposes of the VBL spinning cursor task & removes memory allocated for the
  546. ; task.  also unloads the cursors from the heap.
  547.  
  548. stopAndRemoveSpinningCursor    PROC     EXPORT
  549.     
  550.         IMPORT    gtheTaskPtr : DATA
  551.         IMPORT    gtheVBLPtr : DATA
  552.              
  553.                 MOVE.L    sg.gtheVBLPtr, a0
  554.                 _VRemove
  555.                 
  556.                 MOVE.L    sg.gtheVBLPtr, a0
  557.                 _DisposPtr
  558.                 
  559.                 MOVE.L    sg.gtheTaskPtr, a0
  560.                 _DisposPtr
  561.                 
  562.                 ; unload the cursors 
  563.                 CLR.L    -(sp)
  564.                 MOVE.L    #'CURS', -(sp)
  565.                 MOVE    #1001, -(sp)
  566.                 _GetResource
  567.                 _ReleaseResource
  568.     
  569.                 CLR.L    -(sp)
  570.                 MOVE.L    #'CURS', -(sp)
  571.                 MOVE    #1002, -(sp)
  572.                 _GetResource
  573.                 _ReleaseResource
  574.     
  575.                 CLR.L    -(sp)
  576.                 MOVE.L    #'CURS', -(sp)
  577.                 MOVE    #1003, -(sp)
  578.                 _GetResource
  579.                 _ReleaseResource
  580.     
  581.                 CLR.L    -(sp)
  582.                 MOVE.L    #'CURS', -(sp)
  583.                 MOVE    #1004, -(sp)
  584.                 _GetResource
  585.                 _ReleaseResource
  586.  
  587.                 rts
  588.                 
  589.         ENDP
  590. ;--------------------------------------
  591.         END                ; end of this source file
  592.